//
//  HLZegoLiveKit.m
//  YueYue
//
//  Created by hulu001 on 2024/3/12.
//

#import "HLZegoLiveKit.h"

@interface HLZegoLiveKit ()<ZegoEventHandler,ZegoAudioDataHandler,ZegoCustomVideoCaptureHandler>

@property (nonatomic, strong) dispatch_queue_t queue;

@property (nonatomic, strong) UIView *localView;
@end

@implementation HLZegoLiveKit

+ (instancetype)sharedInstance
{
  static HLZegoLiveKit *sharedInstance = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedInstance = [[self alloc] init];
  });
  return sharedInstance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        _queue = dispatch_queue_create("LLLL", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

- (void)start
{
    ZegoEngineProfile *profile = [[ZegoEngineProfile alloc] init];
    profile.appID = LIVE_APPID;
   // profile.appSign = @"d097730a1ea54e0bbf0fc8657da575487ce1440769f7deaa0b2bf80f40788cf9";
    profile.scenario = ZegoScenarioDefault;
    [ZegoExpressEngine createEngineWithProfile:profile eventHandler:self];
    
    self.user = [ZegoUser userWithUserID:HLRunTime.shareInstance.mine.userId userName:HLRunTime.shareInstance.mine.nickName];
    
    self.users = @[];
}

#pragma mark - （用户）API驱动

/// 加入直播间
- (void)joinWithFemale:(HLLiveFemaleModel *)female localView:(UIView *)localView
{
    self.female = female;
    self.localView = localView;
    
    
    if (self.tokenHandler) {
        MJWeakSelf;
        UInt64 callidValue = strtoull([self.user.userID UTF8String], NULL, 0);
        self.tokenHandler(callidValue, ^(NSString *token, NSError *error) {
            ZegoRoomConfig *config = [[ZegoRoomConfig alloc] init];
            config.isUserStatusNotify = YES;
            config.token = token;
            [[ZegoExpressEngine sharedEngine] loginRoom:female.liveRoomCode user:weakSelf.user config:config];
        });
    }
    
}

/// 离开直播间
- (void)leaveWithCallback:(HLCommonCallback)callback
{
    // 停止拉流
    [[ZegoExpressEngine sharedEngine] stopPlayingStream:_female.liveStreamId];
    // 退出房间
    [[ZegoExpressEngine sharedEngine] logoutRoom];
    
    // 销毁引擎
    [ZegoExpressEngine destroyEngine:nil];
    
    self.delegate = nil;
    
    if (callback) {
        callback(@"122");
    }
}


/// 是否开启摄像头
/// @param enable 是否开启
- (void)enableLocalVideo:(BOOL)enable
{
    [[ZegoExpressEngine sharedEngine] enableCamera:enable];// 连自己都看不到预览
}

/// 麦克风静音
/// @param mute YES：静音 NO：开启
- (void)live_muteLocalAudio:(BOOL)mute
{
    [ZegoExpressEngine.sharedEngine muteMicrophone:mute];
}

- (void)setLoudSpeakerMode:(BOOL)speaker error:(NSError * _Nullable __autoreleasing *)error
{
    [ZegoExpressEngine.sharedEngine muteSpeaker:speaker];
}

- (void)sendCustomSingleControl:(NSString *)command
{
    [[ZegoExpressEngine sharedEngine] sendCustomCommand:command toUserList:self.users roomID:_female.liveRoomCode callback:^(int errorCode) {
    }];
}

#pragma mark - ZegoEventHandler

- (void)onRoomStateChanged:(ZegoRoomStateChangedReason)reason errorCode:(int)errorCode extendedData:(NSDictionary *)extendedData roomID:(NSString *)roomID
{
    if (reason == ZegoRoomStateChangedReasonLoginFailed) {
        // 登录房间失败。当登录房间或切换房间失败后，进入该状态，表示登录房间或切换房间已经失败，例如 AppID 或 AppSign 不正确等。
    } else if (reason == ZegoRoomStateChangedReasonLogined) {
        [self _startPlaying];
    } else if (reason == ZegoRoomStateChangedReasonReconnecting){
        // 房间连接临时中断。如果因为网络质量不佳产生的中断，SDK 会进行内部重试。
    } else if (reason ==  ZegoRoomStateChangedReasonKickOut){
        // 被服务器踢出房间。例如有相同用户名在其他地方登录房间导致本端被踢出房间，会进入该状态。
    } else if (reason == ZegoRoomStateChangedReasonLogout){
//        if ([self.delegate respondsToSelector:@selector(live_onCallEnd)]) {
//            [self.delegate live_onCallEnd];
//        }
    }
}

- (void)onRoomUserUpdate:(ZegoUpdateType)updateType userList:(NSArray<ZegoUser *> *)userList roomID:(NSString *)roomID
{
    
    NSMutableArray *users = [NSMutableArray arrayWithArray:self.users];
    if (updateType == ZegoUpdateTypeAdd) {
        [users addObjectsFromArray:userList];
        if ([self.delegate respondsToSelector:@selector(live_onUserEnter:)]) {
            [self.delegate live_onUserEnter:userList];
        }
    } else {
        NSArray *tempUsers = [NSArray arrayWithArray:users];
        for (ZegoUser *user in tempUsers) {
            for (ZegoUser *rUser in userList) {
                if ([rUser.userID isEqualToString:user.userID]) {
                    [users removeObject:user];
                }
            }
        }
        
        if ([self.delegate respondsToSelector:@selector(live_onUserLeave:)]) {
            [self.delegate live_onUserLeave:userList];
        }
    }
    self.users = users;
}

/// 房间内音视频多媒体流发生变化 有对方新增的流，将其拉入渲染
- (void)onRoomStreamUpdate:(ZegoUpdateType)updateType streamList:(NSArray<ZegoStream *> *)streamList extendedData:(NSDictionary *)extendedData roomID:(NSString *)roomID
{
    if (updateType == ZegoUpdateTypeDelete && streamList.count == 1) {
        if ([self.delegate respondsToSelector:@selector(live_onCallEnd)]) {
            [self.delegate live_onCallEnd];
        }
    }
}

- (void)onPublisherStateUpdate:(ZegoPublisherState)state errorCode:(int)errorCode extendedData:(NSDictionary *)extendedData streamID:(NSString *)streamID
{
    if (errorCode != 0) {
            NSLog(@"推流状态出错 errorCode: %d", errorCode);
        } else {
            switch (state) {
                case ZegoPublisherStatePublishing:
                    NSLog(@"正在推流");
                    break;
                case ZegoPublisherStatePublishRequesting:
                    NSLog(@"正在请求推流");
                    break;
                case ZegoPublisherStateNoPublish:
                    NSLog(@"没有推流");
                    break;
            }
        }
}

- (void)onIMRecvCustomCommand:(NSString *)command fromUser:(ZegoUser *)fromUser roomID:(NSString *)roomID
{
    if ([command isEqualToString:@"pf_live_close"]) {
        [self _logoutRoom];
        if ([self.delegate respondsToSelector:@selector(live_onCallEnd)]) {
            [self.delegate live_onCallEnd];
        }
        return;
    }
    if ([self.delegate respondsToSelector:@selector(live_onRecievedCustom:user:)]) {
        [self.delegate live_onRecievedCustom:command user:fromUser];
    }
    
}


- (void)_enableAudioDataCallback:(BOOL)enable {
    // 音频数据类型 (Bitmask)，此处示例三个回调都开启
    // The required audio data type (Bitmask), all three callbacks are enabled here
    ZegoAudioDataCallbackBitMask bitmask = ZegoAudioDataCallbackBitMaskCaptured | ZegoAudioDataCallbackBitMaskPlayback | ZegoAudioDataCallbackBitMaskMixed;

    // 音频数据参数，此处示例单声道、16K
    // Required audio data parameters, the example here is mono, 16K
    ZegoAudioFrameParam *param = [[ZegoAudioFrameParam alloc] init];
    param.channel = ZegoAudioChannelStereo;
    param.sampleRate = ZegoAudioSampleRate8K;

    // 开启获取原始音频数据的功能
    // Enable the function of obtaining raw audio data
    if (enable) {
        [[ZegoExpressEngine sharedEngine] startAudioDataObserver:bitmask param:param];
    } else {
        [[ZegoExpressEngine sharedEngine] stopAudioDataObserver];
    }
}

- (void)_logoutRoom
{
    // 退出房间
    [[ZegoExpressEngine sharedEngine] logoutRoom];
    // 销毁引擎
    [ZegoExpressEngine destroyEngine:nil];
}


#pragma mark - 拉流

- (void)_startPlaying
{
    
    ZegoCanvas *previewCanvas = [ZegoCanvas canvasWithView:_localView];
    previewCanvas.viewMode = ZegoViewModeAspectFill;
    [[ZegoExpressEngine sharedEngine] startPlayingStream:_female.liveStreamId canvas:previewCanvas];
}





@end
